package com.ficus.road.maintain.util;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

/**
 * @author xiawen yang
 * @date 2022/4/18 下午5:30
 */
@Data
@Component
@Slf4j
public class ZHTokenUtil {
    protected static Integer connectTimeout = 20000;
    /**
     * <timestamp, token>
     */
    public volatile MutablePair<Long, String> availToken = new MutablePair<>(0L, "-");
    @Value("${zhonghai.ip}")
    private String ip;
    @Value("${zhonghai.port}")
    private int port;
    @Value("${zhonghai.webServicePort}")
    private int webServicePort;
    @Value("${zhonghai.username}")
    private String username;
    @Value("${zhonghai.password}")
    private String password;

    private static String getWebserviceResponse(String url, String method, String data, String header) throws Exception {
        byte[] buf = data.getBytes();
        URL uri = new URL(url);
        HttpURLConnection httpConn = (HttpURLConnection) uri.openConnection();
        httpConn.setRequestMethod(method);
        httpConn.setRequestProperty("Content-Type", "application/json");
        httpConn.setRequestProperty("Content-Length", String.valueOf(buf.length));
        if (header != null && !"".equals(header)) {
            httpConn.setRequestProperty("Authorization", header);
        }
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);
        httpConn.setChunkedStreamingMode(0);
        httpConn.setConnectTimeout(connectTimeout);
        httpConn.setReadTimeout(connectTimeout);
        httpConn.connect();
        OutputStream out = httpConn.getOutputStream();
        out.write(buf);
        out.close();
        int code = httpConn.getResponseCode();
        StringBuilder sb;
        if (code == HttpURLConnection.HTTP_OK) {
            InputStreamReader isr = new InputStreamReader(httpConn.getInputStream(), StandardCharsets.UTF_8);
            BufferedReader br = new BufferedReader(isr);
            sb = new StringBuilder();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            br.close();
            isr.close();
        } else {
            throw new Exception("中海状态码异常, 状态码: " + code);
        }
        return sb.toString();
    }

    @PostConstruct
    void initToken() {
        getRemoteToken();
    }

    @Scheduled(cron = "0 0/10 * * * ?")
    void refreshToken() {
        getRemoteToken();
    }

    public String getLocalToken() {
        return availToken.getRight();
    }

    public String getRemoteToken() {
        String host = ip + ":" + webServicePort + "/hbzs/";
        String dataTemplate = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
                "<SOAP-ENV:Body>%s" +
                "</SOAP-ENV:Body>" +
                "</SOAP-ENV:Envelope>";
        String data = String.format(dataTemplate, "<m:doLogin xmlns:m=\"http://intf.services.user.sys.modules.sysmodules.scdp.csnt.com/\">" +
                "<arg0><username>" + username + "</username>" + "<password>" + password + "</password>" + "</arg0>" + "</m:doLogin>");
        String rlt;
        try {
            rlt = getWebserviceResponse("http://" + host + "/services/Login", "POST", data, null);
        } catch (Exception e) {
            log.error("中海登录接口异常, 异常信息: ", e);
            return null;
        }

        int startIndex = rlt.indexOf("<return>") + 8;
        int endIndex = rlt.indexOf("</return>", startIndex);
        String token = rlt.substring(startIndex, endIndex);
        availToken.setLeft(System.currentTimeMillis());
        availToken.setRight(token);
        log.info("refresh token success");
        return token;
    }
}
